/**Gateway+Resilience4j+Eureka
 * 1）依赖库：SpringCloud版本为2020.0.0及以上，核心依赖为spring-cloud-starter-circuitbreaker-reactor-resilience4j
 * 2）注入一个ReactiveResilience4JCircuitBreakerFactory
 * 3）实现一个降级服务用的controller（FallbackController），在其中定义降级方法
 * 4）在配置文件（yml）中定义路由的filters:为CircuitBreaker，并配置名称和降级uri（与上一步骤中一致）
 * 5）在配置文件（yml）中配置Hystrix其它属性。
 */
package com.example.demogatewaycircuitbreaker;

import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.timelimiter.TimeLimiterConfig;
import io.github.resilience4j.timelimiter.TimeLimiterRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JCircuitBreakerFactory;
import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JConfigBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import reactor.core.publisher.Mono;

import java.time.Duration;

@SpringBootApplication
@EnableDiscoveryClient
public class DemoGatewayCircuitbreakerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoGatewayCircuitbreakerApplication.class, args);
    }


    @Bean
    public ReactiveResilience4JCircuitBreakerFactory defaultCustomizer(CircuitBreakerRegistry circuitBreakerRegistry, TimeLimiterRegistry timeLimiterRegistry) {

        ReactiveResilience4JCircuitBreakerFactory factory = new ReactiveResilience4JCircuitBreakerFactory(circuitBreakerRegistry,timeLimiterRegistry);
        factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
                //超时规则,默认1s
                .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofMillis(10000)).build())
                .build());
        //添加自定义拦截器
        factory.configureCircuitBreakerRegistry(circuitBreakerRegistry);
        return factory;
    }


    @Bean
    @Primary
    public KeyResolver ipKeyResolver() {

        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString());

    }


    /*用户限流*/
    @Bean
    KeyResolver userKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));

    }

    //接口限流
    @Bean
    KeyResolver apiKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getPath().value());
    }


}
